﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// C#时间起始点为0001年1月1日午夜12点0分0秒0毫秒
/// Java等时间起始点为1970年1月1日 0点0分0秒0毫秒
/// 
/// 需要和服务器在游戏一开始进行时钟同步，在每次心跳时重新同步
/// </summary>
namespace SG
{
    public class TimeUtils
    {
        // 十进制显示
        //Decimal dec = new Decimal(ms);
        //DebugLogger.Print(dec.ToString());
        public enum TimeFormat
        {
            HHMMSS,
            MMSS,
            SS,
            HHMM,
            DDHHMMSS,

            HHMMSS_Lang,
            MMSS_Lang,
            SS_Lang,
            HHMM_Lang,
        }

        public enum TimeTypeId
        {
            Realtime,
            Timescale
        }

        // 设置为本地时区
        static DateTimeKind msTimeKind = DateTimeKind.Local;
        //TimeZone;

        static private float msTimeScale = 1.0f;
        public static float deltaTime
        {
            get
            {
                return Time.deltaTime;
            }
        }

        /// <summary>
        /// 真实帧时差,不受Unity3d时间缩放参数影响
        /// </summary>
        public static float realDeltaTime
        {
            get
            {
                return Time.unscaledDeltaTime;
            }
        }

        static public void SetTimeScale(float scale)
        {
            Time.timeScale = scale;
        }

        static public void StopTimeScale(float scale = 1f)
        {
            Time.timeScale = scale;
        }

        /// <summary>
        /// 日期
        /// </summary>
        public static long currentMillisecond
        {
            get
            {
                // Ticks unit is 100 毫微秒
                // 由于精度问题不能使用float
                if (msTimeKind == DateTimeKind.Utc)
                {
                    return DateTime.UtcNow.Ticks / 10000L;
                }
                else if (msTimeKind == DateTimeKind.Local)
                {
                    return DateTime.Now.Ticks / 10000L;
                }

                return DateTime.Now.Ticks / 10000L;
            }
        }

        static public long currentSeconds
        {
            get
            {
                return (currentMillisecond / 1000L);
            }
        }

        /// <summary>
        /// 临时处理，与javaStandardDateTime相加
        /// </summary>
        /// <param name="millisecond"></param>
        /// <returns></returns>
        static public long ConvertServerTime2Local(long millisecond)
        {
            long result = millisecond + (javaStandardDateTime.Ticks / 10000L) + (dateTimeOffsetTicks / 10000L);
            return result;
        }

        static public long ConvertLocalTime2Server(long ticks)
        {
            long result = (ticks - javaStandardDateTime.Ticks - dateTimeOffsetTicks) / 10000L;
            return result;
        }

        //---------------------------------------------------------------------------------------------------
        /// <summary>
        /// 同步时间，可作为基准值处理，单位为毫秒
        /// </summary>
        static private long msSyncServerTime = 0L;
        static private double msSyncLocalRealTime = 0.0f;

        /// <summary>
        /// 与服务器进行时钟同步，可定时处理
        /// </summary>
        /// <param name="tm"></param>
        static public void SyncServerTime(long tm)
        {
            msSyncServerTime = tm;
            msSyncLocalRealTime = (double)Time.realtimeSinceStartup;
        }

        public static long GetCurrentServerTime()
        {
            double timeSpan = (double)Time.realtimeSinceStartup - msSyncLocalRealTime;
            return msSyncServerTime + (long)(timeSpan * 1000L);
        }

        public static int GetCurrentServerSeconds()
        {
            return (int)(GetCurrentServerTime() / 1000);
        }

        public static int GetServerTimeSpan(long serverTime)
        {
            long currentMillisecond = TimeUtils.GetCurrentServerTime();
            long serverMillisecond = serverTime;

            int tSecondSpan = (int)((serverMillisecond - currentMillisecond) / 1000L);
            if (tSecondSpan < 0)
            {
                tSecondSpan = 0;
            }
            return tSecondSpan;
        }

        public static DateTime GetCurrentServerDateTime()
        {
            long time = ConvertServerTime2Local(GetCurrentServerTime());
            return new DateTime(time * 10000L);
        }

        //-------------------------------------------------------------------------------------------------------
        public const int ONE_DAY_HOURS = 24;
        public const int ONE_DAY_SECONDS = 86400;
        public const int ONE_HOUR_MINUTES = 60;
        public const int ONE_HOUR_SECONDS = 3600;
        public const int ONE_MINUTE_SECONDS = 60;

        public static long GetDateTimeMillisecond(DateTime a)
        {
            if (msTimeKind == DateTimeKind.Utc)
            {
                return a.Ticks / 10000L;
            }
            else if (msTimeKind == DateTimeKind.Local)
            {
                return a.Ticks / 10000L;
            }

            return a.Ticks / 10000L;
        }

        public static int DeltaSeconds(DateTime a, DateTime b)
        {
            return (int)a.Subtract(b).TotalSeconds;
        }

        public static int GetTimeStamp(DateTime dt, DateTime dt1)
        {
            return TimeUtils.DeltaSeconds(dt, dt1);
        }

        public static int GetTimeStamp(long dt, long dt1)
        {
            int millSecondSpan = (int)Mathf.Abs(dt - dt1);
            return millSecondSpan / 1000;
        }

        public static int GetTimeOfDay(int hour, int minute, int second)
        {
            return hour * ONE_HOUR_SECONDS + minute * ONE_MINUTE_SECONDS + second;
        }

        // Java等时间起始点为1970年1月1日 0点0分0秒0毫秒
        private static readonly DateTime javaStandardDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        private static readonly long dateTimeOffsetTicks = (DateTimeOffset.Now.Ticks - DateTimeOffset.Now.UtcTicks);

        public static DateTime GetStandardDateTime()
        {
            return TimeUtils.javaStandardDateTime;
        }

        public static DateTime GetDateTime(string strTime)
        {
            return Convert.ToDateTime(strTime);
        }

        public static DateTime GetDateTime(long millisecond)
        {
            return new DateTime(TimeUtils.ConvertServerTime2Local(millisecond) * 10000L);
        }

        public static int GetTimeStamp(DateTime dt)
        {
            return TimeUtils.DeltaSeconds(dt, TimeUtils.javaStandardDateTime);
        }

        public static DateTime GetNextDateTime(int hour, int minute, int second)
        {
            DateTime now = DateTime.Now;
            int num = (int)now.TimeOfDay.TotalSeconds;
            int timeOfDay = TimeUtils.GetTimeOfDay(hour, minute, second);
            int num2 = (num >= timeOfDay) ? (timeOfDay + 86400 - num) : (timeOfDay - num);
            return now.AddSeconds((double)num2);
        }
        public static int GetNextTimeStamp(int hour, int minute, int second)
        {
            DateTime nextDateTime = TimeUtils.GetNextDateTime(hour, minute, second);
            return TimeUtils.GetTimeStamp(nextDateTime);
        }

        /// <summary>
        /// 获取当前月的天数
        /// </summary>
        /// <returns></returns>
        static public int GetDaysNumInThisMonth()
        {
            DateTime dtNow = DateTime.Now;
            int days = DateTime.DaysInMonth(dtNow.Year, dtNow.Month);
            return days;
        }

        /// <summary>
        /// 获取当前天数
        /// </summary>
        /// <returns></returns>
        static public int GetDayInThisMonth()
        {
            return DateTime.Now.Day;
        }

        /// <summary>
        /// Format EnumList
        /// </summary>
        private static Dictionary<TimeFormat, string> msTimeFormatDict;

        private static void InitTimeFormatDictionary()
        {
            if (msTimeFormatDict == null)
            {
                msTimeFormatDict = new Dictionary<TimeFormat, string>();
                //msTimeFormatDict[TimeFormat.HHMMSS_Lang] = MultipleLanguage.FormatValue(LocalizationKeyDefines.HHMMSS_Lang);
                //msTimeFormatDict[TimeFormat.MMSS_Lang] = MultipleLanguage.FormatValue(LocalizationKeyDefines.MMSS_Lang);
                //msTimeFormatDict[TimeFormat.SS_Lang] = MultipleLanguage.FormatValue(LocalizationKeyDefines.SS_Lang);
                //msTimeFormatDict[TimeFormat.HHMM_Lang] = MultipleLanguage.FormatValue(LocalizationKeyDefines.HHMM_Lang);

                //msTimeFormatDict[TimeFormat.DDHHMMSS] = MultipleLanguage.FormatValue(LocalizationKeyDefines.DDHHMMSS);

            }
        }

        private static string GetTimeFormatLang(TimeFormat format)
        {
            InitTimeFormatDictionary();
            return msTimeFormatDict[format];
        }

        public static string FormatDateTime(long milliseconds, bool isLocal = false)
        {
            if (!isLocal)
            {
                milliseconds = ConvertServerTime2Local(milliseconds);
            }

            long ticks = milliseconds * 10000L;
            return new DateTime(ticks).ToString("HH:mm:ss");
        }

        public static string FormatDateTimeLong(long milliseconds, bool isLocal = false)
        {
            if (!isLocal)
            {
                milliseconds = ConvertServerTime2Local(milliseconds);
            }

            long ticks = milliseconds * 10000L;
            DateTime dateTime = new DateTime(ticks);

            string result = string.Format("{0}月{1}日{2}", dateTime.Month, dateTime.Day, dateTime.ToString("HH:mm:ss"));
            return result;
        }

        public static string FormatDateTimeShort(long milliseconds)
        {
            long ticks = milliseconds * 10000L;
            return new DateTime(ticks).ToShortDateString().ToString();
        }

        public static string FormatSeconds(int seconds, TimeFormat format)
        {
            int day = seconds / ONE_DAY_SECONDS;
            int hour = seconds / ONE_HOUR_SECONDS;
            int modHour = hour % ONE_DAY_HOURS;
            int modSecond = seconds % ONE_HOUR_SECONDS;
            int minute = modSecond / ONE_MINUTE_SECONDS;
            int second = modSecond % ONE_MINUTE_SECONDS;
            switch (format)
            {
                case TimeFormat.HHMMSS:
                    return string.Format("{0}:{1:D2}:{2:D2}", hour, minute, second);
                case TimeFormat.MMSS:
                    return string.Format("{0}:{1:D2}", hour * ONE_HOUR_MINUTES + minute, second);
                case TimeFormat.SS:
                    return seconds.ToString();
                case TimeFormat.HHMM:
                    return string.Format("{0}:{1:D2}", hour, minute);
                case TimeFormat.DDHHMMSS:
                    return string.Format(GetTimeFormatLang(format), day, modHour, minute, second);
                case TimeFormat.HHMMSS_Lang:
                    return string.Format(GetTimeFormatLang(format), hour, minute, second);
                case TimeFormat.MMSS_Lang:
                    return string.Format(GetTimeFormatLang(format), hour * ONE_HOUR_MINUTES + minute, second);
                case TimeFormat.SS_Lang:
                    return string.Format(GetTimeFormatLang(format), seconds);
                case TimeFormat.HHMM_Lang:
                    return string.Format(GetTimeFormatLang(format), hour, minute);
            }
            return seconds.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="seconds"></param>
        /// <returns></returns>
        public static string FormatSecondsCompareNow(long milliseconds, bool isLocal = false)
        {
            string result = string.Empty;

            long nowMilliseconds = !isLocal ? GetCurrentServerTime() : System.DateTime.Now.Ticks / 10000L;
            int secondStamp = TimeUtils.GetTimeStamp(milliseconds, nowMilliseconds);

            bool bTimeAgo = nowMilliseconds > milliseconds;
            if (secondStamp > 3 * TimeUtils.ONE_DAY_SECONDS)
            {
                result = TimeUtils.GetDateTime(milliseconds).ToString("yyyy年MM月dd日");
            }
            else
            {
                // 刚刚 3分钟前  3小时前 2天前
                int day = secondStamp / ONE_DAY_SECONDS;
                int hour = secondStamp / ONE_HOUR_SECONDS;
                int modHour = hour % ONE_DAY_HOURS;
                int modSecond = secondStamp % ONE_HOUR_SECONDS;
                int minute = modSecond / ONE_MINUTE_SECONDS;
                int second = modSecond % ONE_MINUTE_SECONDS;

                string timeSuffix = bTimeAgo ? "Ago" : "Later";
                //if (day > 0)
                //{
                //    result = MultipleLanguage.FormatValue(string.Format("_DD{0}", timeSuffix), day);
                //}
                //else if (hour > 0)
                //{
                //    result = MultipleLanguage.FormatValue(string.Format("_HH{0}", timeSuffix), hour);
                //}
                //else if (minute > 0)
                //{
                //    result = MultipleLanguage.FormatValue(string.Format("_MM{0}", timeSuffix), minute);
                //}
                //else
                //{
                //    result = MultipleLanguage.GetValue("_JustNow");
                //}
            }

            return result;
        }
        public static long TimeInMilliseconds()
        {
            TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - javaStandardDateTime.Ticks);
            return (long)ts.TotalMilliseconds;
        }

    }
}
